erpcfile(context) ::= <<
<! ================================================================================== !>
<! =                                                                                = !>
<! = top-level thrift file definition                                               = !>
<! =                                                                                = !>
<! = called from the generator to render a new thrift source file.                  = !>
<! =                                                                                = !>
<! ================================================================================== !>
program <context.programName>

<context.enums : {e | <_enum(e)>}; separator="\n\n">

<context.structs : {s | <_struct(s)>}; separator="\n\n">

<context.services : {s | <_service(s)>}; separator="\n\n">

>>

_enum(enum) ::= <<
<_doc(enum.documentation)><\\\>
enum <enum.enumName> {
<_enumExtension(enum.extensiveItemsBefore)>
  <enum.elementsDocumentation : {enumElem | <_doc(enum.elementsDocumentation.(enumElem))><\\\>
  <enumElem><_maybeEnumValue(enum, enumElem)>}; separator=",\n">
<_enumExtension(enum.extensiveItemsAfter)>
}
>>

_enumExtension(items) ::= <<
  <items : {item | <_doc(item.documentation)><\\\>
  <enum.enumClass.simpleName>_<item.name>_c<if(item.constant)>=<item.constant><endif>}; separator=",\n">
>>

_maybeEnumValue(enum, enumElem) ::= <<
<if(enum.byEnumConstant)>=<enum.byEnumConstant.(enumElem)><endif>
>>

_struct(struct) ::= <<
<_doc(struct.documentation)><\\\>
<_structkind(struct)> <struct.structName> {
  <struct.fields : {f | <if(!f.internal)><_member(f)>;<endif>}; separator="\n">
}
>>

_structkind(struct) ::= <<
<if(struct.struct)>struct<endif><if(struct.exception)>struct<endif><if(struct.union)>union<endif>
>>

_member(member) ::= <<
<_doc(member.documentation)><\\\>
<member.typePrefix><_memberType(member)> <member.memberName><if(!member.canPrimitive)><_fieldRequiredness(member)><member.sizeLimit><endif>
>>

_memberType(member) ::= <<
<if(member.preAlloc)><member><else><member.thriftType><endif>
>>

_field(field) ::= <<
<_doc(field.documentation)><\\\>
<field.thriftType> <field.name><_fieldRequiredness(field)><field.sizeLimit>
>>

_fieldRequiredness(field) ::= <<
<if(field.preAlloc)><elseif(!field.erpcType.javaClass.primitive && !field.erpcType.javaClass.enum)><if(field.requiredness)><field.requiredness><endif><endif>
>>

_service(service) ::= <<
<_doc(service.documentation)><\\\>
interface <service> {
  <service.declaredMethods : {method | <_method(service.declaredMethods.(method))>}; separator="\n">
}
>>

_method(method) ::= <<
<_doc(method.documentation)><\\\>
<if(method.oneway)>oneway <endif><\\\>
<context.portPrefix><method.name><\\\>
(<_returnValue(method)><_methodParameters(method.parameters)>)<\\\>
-> <if(context.erpcProxyReturnType)><context.erpcProxyReturnType><else>int32<endif><\\\>
;
>>

_returnValue(method) ::= <<
out string _err_msg@max_length(<context.errmsgMaxLength>)<if(!method.erpcReturnType.void)>,out <method.erpcReturnType> _return<\\\>
<_maxlength(method.erpcReturnType)><\\\>
<endif><if(!method.parameters.empty)>, <endif>
>>

_maxlength(erpcType) ::= <<
<if(erpcType.protocolType.string)> @max_length(<context.defaultMaxLength>)<endif>
>>

_nullable(erpcType) ::= <<
<if(!erpcType.unwrappedJavaType.primitive)> @nullable<endif>
>>

_methodParameters(params) ::= <<
<params : {p | in <_field(p)>}; separator=", ">
>>

_doc(documentation) ::= <<
<if(documentation)>
/*!
<documentation : {line |  * <line>}; separator="\n">
 */
<endif>
>>
